package com.hwy.widget.suck_top

import android.content.Context
import android.graphics.Canvas
import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlin.math.min

/**
 * =======================================
 * 作者: hewenyu
 * 日期: 2022/2/19 13:32
 * 说明: RecyclerView分组名称悬浮显示
 * =======================================
 */
abstract class AbstractSuckTopDecoration(
    val context: Context,
    var headerHeight: Int,  // 分组名称高度
    var decorationHeight: Int = 0   // 分割线高度
) :
    RecyclerView.ItemDecoration() {

    /**
     * 分组标题绘制的区域
     */
    private val boundsRect by lazy {
        Rect()
    }

    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        super.getItemOffsets(outRect, view, parent, state)
        // 获取View的位置
        val position = parent.getChildLayoutPosition(view)
        if (!isOnlyDrawSuckTop() && isGroupHeader(position)) {
            // 预留header的区域
            outRect.set(0, headerHeight, 0, 0)
        } else if (!isGroupHeader(position)) {
            // 预留分割线的高度
            outRect.set(0, decorationHeight, 0, 0)
        }
    }

    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDraw(c, parent, state)
        val count = parent.childCount
        val left = parent.paddingLeft
        val right = parent.width - parent.paddingRight
        for (i in 0 until count) {
            val view = parent.getChildAt(i)
            // 获取 view 的位置
            val position = parent.getChildLayoutPosition(view)
            if (!isOnlyDrawSuckTop() && view.top - headerHeight - parent.paddingTop >= 0) {
                boundsRect.set(left, view.top - headerHeight, right, view.top)
                drawGroupHeader(boundsRect, c, parent, position, false)
            } else if (view.top - headerHeight - parent.paddingTop >= 0) {
                boundsRect.set(left, view.top - decorationHeight, right, view.top)
            }
        }
    }

    override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDrawOver(c, parent, state)
        (parent.layoutManager as? LinearLayoutManager)?.run {
            val position = findFirstVisibleItemPosition()
            if (position == RecyclerView.NO_POSITION) {
                return@run
            }
            // 获取对应 position 的view
            parent.findViewHolderForAdapterPosition(position)?.run {
                val left = parent.paddingLeft
                val right = parent.width - parent.paddingRight
                val top = parent.paddingTop
                var bottom = top + headerHeight
                if (isGroupHeader(position + 1)) {
                    // 判断当前显示的第二个位置的item是否是分组的第一个item
                    // 处理两个header顶住的效果
                    bottom = min(headerHeight, itemView.bottom - parent.paddingTop)
                }
                boundsRect.set(left, top, right, bottom)
                drawGroupHeader(boundsRect, c, parent, position, true)
            }
        }
    }

    /**
     * 是否只绘制吸顶效果的header
     * true: 只绘制吸顶的header，每个分组的header需要由分组的item布局自己实现
     * false: 除了绘制吸顶的header，还需要绘制每个分组的header
     */
    protected open fun isOnlyDrawSuckTop() = false

    /**
     * 绘制decoration，当前 decoration 的位置位于每个item的顶部
     */
    protected open fun drawDecoration(
        boundsRect: Rect,
        canvas: Canvas,
        parent: RecyclerView,
        position: Int
    ) {

    }

    /**
     * 判断[position]位置是否是分组的第一个位置
     */
    abstract fun isGroupHeader(position: Int): Boolean

    /**
     * 绘制分组header区域内容
     * [boundsRect]: 需要绘制header的区域
     * [position]: 绘制header对应item的位置
     * [isSuckTopHeader]: 当前header是否是吸顶的header
     */
    abstract fun drawGroupHeader(
        boundsRect: Rect,
        canvas: Canvas,
        parent: RecyclerView,
        position: Int,
        isSuckTopHeader: Boolean
    )
}